﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Inspired.Euler
{
    /// <summary>
    /// If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.
    /// 
    /// If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?
    /// 
    /// </summary>
    /// <remarks>
    /// NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 
    /// 115 (one hundred and fifteen) contains 20 letters. The use of "and" when writing out numbers is in compliance 
    /// with British usage.
    /// </remarks>
    public static class Problem017
    {
        /// <summary>
        /// How many letters would be needed to write all the numbers in words from 1 to 1000?
        /// </summary>
        [EulerProblem(17, Title = "How many letters would be needed to write all the numbers in words from 1 to 1000?")]
        public static long Solve()
        {
            Dictionary<int, string> cardinals = new Dictionary<int, string>()
            {
                { 1, "one" }, { 2, "two" }, { 3, "three" }, { 4, "four" }, { 5, "five" }, { 6, "six" }, { 7, "seven" }, { 8, "eight" }, { 9, "nine" },
                { 11, "eleven" }, { 12, "twelve" }, { 13, "thirteen" }, { 14, "fourteen" }, { 15, "fifteen" }, { 16, "sixteen" }, { 17, "seventeen" }, { 18, "eighteen" }, { 19, "nineteen" },
                { 10, "ten" }, { 20, "twenty" }, { 30, "thirty" }, { 40, "forty" }, { 50, "fifty" }, { 60, "sixty" }, { 70, "seventy" }, { 80, "eighty" }, { 90, "ninety" },
            };

            List<string> numerals = new List<string>()
            {
                "",
                " hundred",
                " thousand",
                " million",
                " billion"
            };

            long count = 0;
            for (int n = 1; n <= 1000; n++)
            {
                int number = n;
                int position = 0;
                List<string> words = new List<string>();
                while (number > 0)
                {
                    string word = "";
                    int digits = (number % 100);
                    if (digits > 0)
                    {
                        if (!cardinals.TryGetValue(digits, out word))
                            word = cardinals[digits - (digits % 10)] + "-" + cardinals[digits % 10];

                        words.Insert(0, word + numerals[position]);
                    }
                    
                    number = (number - digits) / (int)Math.Pow(10, 2 + position);
                    position++;
                }
                string literal = String.Join(" and ", words);
                Console.WriteLine("{0} = {1}", n, literal);
                count += literal.Count(c => c != ' ' && c != '-');
            }

            return count;
        }
    }
}
